flushdata(app.vid); % flush data in memory
app.vid.LoggingMode = "memory"; %choose to save image to memory
cam_configure; % refresh cam parameters
if app.triggertype.Value == 'software'
    app.src.DelayTime_s = round(0.1-app.ExposureTimeEditField.Value/1000,4); % frame interval is fixed at 100ms
else
    app.src.DelayTime_s = 0;
end

% generate parameter info for single image and image stack
params_info = sprintf('%s,%d,%d,%d', ...
    app.VideoFilenameEditField.Value,app.ExposureTimeEditField.Value,  ...
    app.BinEditField.Value,app.frameintervalEditField.Value);
% generate video_filename_prefix for image stack
video_filename_prefix = extractBefore(app.VideoFilenameEditField.Value,'.tif');
% assignin("base","video_filename_prefix",video_filename_prefix);

start(app.vid);


% fig_preview = figure('name','Capturing','NumberTitle','off','Position',[400,0,1024,1024],'SizeChangedFcn',@fun_equal_scaling_windows);
% app.preview_hImage = image(zeros(app.vid.VideoResolution));
% preview(app.vid,app.preview_hImage);

fig_preview = figure('name','Capturing','NumberTitle','off','Position',[400,0,1024,1024],'SizeChangedFcn',@fun_equal_scaling_windows);
app.preview_hImage = image(zeros(app.vid.VideoResolution));
ax_preview = gca;
set(ax_preview,'units','normalized');
set(ax_preview,'InnerPosition',[0.13,0.18,0.775,0.815]);

% set up UpdatePreviewWindowFcn callback funtion to change the contrast of preview
setappdata(app.preview_hImage,'UpdatePreviewWindowFcn',@fun_adjust_contrast);
grescale_range=[app.MinGreyEditField.Value,app.MaxGreyEditField.Value];
setappdata(app.preview_hImage,'HandleToGreyScale',grescale_range);
ax_histogram = uiaxes(fig_preview,"Units","normalized","Position",[0.1,0,0.8,0.18]);
ax_histogram.XLabel.String ='intensity';
ax_histogram.YLabel.String ='number of pixels';
setappdata(app.preview_hImage,'HandleToHistogram',ax_histogram);
preview(app.vid,app.preview_hImage);


% fig_preview = figure('name','Capturing','NumberTitle','off','Position',[800,100,1024,1024],'SizeChangedFcn',@fun_equal_scaling_windows);
% app.preview_hImage = image(zeros(app.vid.VideoResolution));
% ax_preview = gca;
% set(ax_preview,'units','normalized');
% set(ax_preview,'InnerPosition',[0.13,0.18,0.775,0.815]);
% 
% % set up UpdatePreviewWindowFcn callback funtion to change the contrast of preview
% setappdata(app.preview_hImage,'UpdatePreviewWindowFcn',@fun_adjust_contrast);
% grescale_range=[app.MinGreyEditField.Value,app.MaxGreyEditField.Value];
% setappdata(app.preview_hImage,'HandleToGreyScale',grescale_range);
% ax_histogram = uiaxes(fig_preview,"Units","normalized","Position",[0.1,0,0.8,0.18]);
% ax_histogram.XLabel.String ='intensity';
% ax_histogram.YLabel.String ='number of pixels';
% setappdata(app.preview_hImage,'HandleToHistogram',ax_histogram);
% preview(app.vid,app.preview_hImage);

% app.ardu_serial.UserData = [];
% fun_send_serial_data(app.ardu_serial,'exposure_time',app.ExposureTimeEditField.Value);
% fun_send_serial_data(app.ardu_serial,'interval',app.frameintervalEditField.Value);
% fun_send_serial_data(app.ardu_serial,'frame_number',app.framenumberEditField.Value);
% pause(0.1);
% fun_send_serial_data(app.ardu_serial,'starter_1',1);

app.remark_info = "";
app.frame_n = 0;

tic

% 在循环外只初始化一次
ts = datestr(now, 'yyyymmdd_HHMMSS');
timestamp_filename = sprintf('%s_%s_timestamps.txt', video_filename_prefix, ts);
logFID = fopen(timestamp_filename, 'a');
while app.captureButton.Text == "stop"
    pause(0.001);
    if app.vid.FramesAvailable > 0
        image_4d = getdata(app.vid,1);
        % image_3d = image_4d(:,:,1,1);
        app.frame_n = app.frame_n + 1;
        output_filename = [video_filename_prefix, '_',num2str(app.frame_n), '.tif'];
        % imwrite(image_4d,output_filename,"Description",[params_info,num2str(app.frame_n)]);
        imwrite(image_4d,output_filename);
        app.CurrentFrameLabel.Text = string(app.frame_n);
        % —— 关键：获取 UNIX 时间戳 —— 
        dt = datetime('now','TimeZone','UTC');          
        unix_ts = posixtime(dt);                       % :contentReference[oaicite:2]{index=2}
        % 输出：文件名、帧号、时间戳（秒，小数点后三位）
        fprintf(logFID, '%s\t%d\t%f\n', output_filename, app.frame_n, unix_ts);
    end

    if app.captureButton.Text == "capture"
        app.captureButton.Enable = 'off';
        pause(0.01);
        % fun_send_serial_data(app.ardu_serial,'starter_1',0);
        break
    end

    % if ~isempty(app.ardu_serial.UserData)
    %     pause(0.001);
    %     break
    % end
end
toc

% fun_send_serial_data(app.ardu_serial,'starter_1',0);
% fun_send_serial_data(app.ardu_serial,'LED_status',0);
stop(app.vid);
% get the rest image data that is still in RAM and save
fun_loginfo(app, 'saving...');

while app.vid.FramesAvailable > 0
    pause(0.001);
    image_4d = getdata(app.vid,1);
    % image_3d = image_4d(:,:,1,1);
    app.frame_n = app.frame_n + 1;
    output_filename = [video_filename_prefix, '_',num2str(app.frame_n), '.tif'];
    % imwrite(image_4d,output_filename,"Description",[params_info,num2str(app.frame_n)]);
    imwrite(image_4d,output_filename);
    app.CurrentFrameLabel.Text = string(app.frame_n);
end

% reset after capturing: close the capturing windows and turn tag number to 0, reset remarkEditField
fun_loginfo(app, app.VideoFilenameEditField.Value);
app.CurrentTagLabel.Text = "0";
app.remarksEditField.Value = "";
try
    close('Capturing')
catch
end

% % for single image, show the result in a new window
% if app.framenumberEditField.Value == 1
%     frame = imread(app.VideoFilenameEditField.Value);
%     fig_preview = figure('name',app.VideoFilenameEditField.Value,'NumberTitle','off','Position',[800,100,1224,1024],'SizeChangedFcn',@fun_equal_scaling_windows);
%     imshow(frame,'Border','tight');
% end

% generate csv file in the end
generate_csv_finally;

% record all capture info to root csv
fun_record_info_to_root_csv(app.excel_filename,app.image_history_folder);

app.captureButton.Text = "capture";
app.captureButton.Enable = 'on';
app.captureButton.FontColor = [0 0.4471 0.7412];
% app.lightonButton.Text = "light on";
% app.lightonButton.FontColor = [0 0.4471 0.7412];
% app.lightonButton.Enable = 'on';
% app.savetoRAMCheckBox.Enable = 'on';
app.previewButton.Enable = 'on';
app.ExposureTimeEditField.Enable = 'on';
% app.GainEditField.Enable = 'on';
app.BinEditField.Enable = 'on';
% app.framenumberEditField.Enable = 'on';
% app.frameintervalEditField.Enable = 'on';
app.VideoFilenameEditField.Enable = 'on';
app.SaveAsButton_1.Enable = 'on';
% app.cellcountButton.Enable = 'on';
app.X0EditField.Enable = 'on';
app.Y0EditField.Enable = 'on';
app.widthEditField.Enable = 'on';
app.heightEditField.Enable = 'on';

clear image_3d image_4d;



